-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added: QTE Framework #1649
base: master
Are you sure you want to change the base?
Added: QTE Framework #1649
Conversation
addons/common/fnc_runQTE.sqf
Outdated
if (!GVAR(settingsInitFinished)) exitWith { | ||
// only run this after the settings are initialized | ||
GVAR(runAtSettingsInitialized) pushBack [FUNC(runQTE), _this]; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now leave this aside, or bring it up-to-date with CBA.
addons/common/fnc_runQTE.sqf
Outdated
TRACE_1("QTE already running qeueing up", GVAR(QTERunning)); | ||
[{ | ||
!GVAR(QTERunning) | ||
}, { | ||
_this call FUNC(runQTE); | ||
}, _this] call CBA_fnc_waitUntilAndExecute; | ||
}; | ||
|
||
private _display = findDisplay 46; | ||
|
||
if (isNull _display) exitWith { | ||
TRACE_1("Waiting for main display to be ready", isNull (_display)); | ||
[{ | ||
!isNull (findDisplay 46) | ||
}, { | ||
_this call FUNC(runQTE); | ||
}, _this] call CBA_fnc_waitUntilAndExecute; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imo it should be up to the user to check whenever it's ready. This should only return false
or an error code that it couldn't run. The removal of these waitUntilAndExecute
would make the _onDisplay
event redundant.
The display on which the QTE is drawn should be an argument, so that people can run it wherever they want to (e.g. Zeus interface). Because of comment below, this is no longer relevant.
addons/common/fnc_runQTE.sqf
Outdated
private _inputKeys = [DIK_UP, DIK_DOWN, DIK_LEFT, DIK_RIGHT]; | ||
switch (GVAR(QTEInputKeys)) do { | ||
case 1: { | ||
_inputKeys = [DIK_W, DIK_S, DIK_A, DIK_D]; | ||
}; | ||
case 2: { | ||
_inputKeys = [DIK_I, DIK_K, DIK_J, DIK_L]; | ||
}; | ||
case 3: { | ||
_inputKeys = [DIK_NUMPAD8, DIK_NUMPAD2, DIK_NUMPAD4, DIK_NUMPAD6]; | ||
}; | ||
default { | ||
_inputKeys = [DIK_UP, DIK_DOWN, DIK_LEFT, DIK_RIGHT]; | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really dislike this strongly. It uses CBA settings for keybind sets, when we can use CBA keybinds instead.
This would allow for way more flexibility and customisability, as 3rd party mods or mod makers could add their own extra keybinds.
Register 4 keybinds. Here's an example (strings would need to be localised and improved):
["QTE Keybinds", QGVAR(keyUpQTE), ["QTE up key", "Up key used in QTE events."], {
["↑"] call FUNC(keyPressedQTE); // return
}, {}, [DIK_UP, [false, false, false]]] call CBA_fnc_addKeybind;
In fnc_keyPressedQTE
, you'd check if the keypress is good or not:
params ["_eventQTE"];
// Check if the passed parameter is the next key in the QTE sequence
// If yes, continue
// If no, stop
Imo, we should make the QTE agonistic of the QTE chars themselves ("↑"). That should be configurable by the user. It will add an extra layer of complexity to the whole things, so we'll have to see if it's worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep it simple and start with assigning keys to "↑" etc then we can look at expanding to other keys.
@johnb432 |
addons/common/XEH_preInit.sqf
Outdated
@@ -78,3 +79,19 @@ activateAddons GVAR(addons); | |||
["CAManBase", "InitPost", CBA_fnc_randomizeFacewear] call CBA_fnc_addClassEventHandler; | |||
|
|||
ADDON = true; | |||
|
|||
["CBA QTE", "QTE_Up_Key", ["↑", "Up key used in QTE events."], {}, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally have a problem with QTE events
cuz it expands into Quick-Time Event events
.
Making it Quick-Time Events
ain't just 2 letters longer, I admit, but shouldn't matter:
Up key used in QTE events.
Up key used in Quick-Time Events.
* [["↑", "↓", "→", "←"]] call ace_common_fnc_getFormattedQTESequence | ||
* | ||
* Public: Yes | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other headers are formatted different from this one.
addons/common/fnc_keyPressedQTE.sqf
Outdated
}; | ||
|
||
if (_onDisplay isEqualType "") then { | ||
[_onDisplay, [_args, _qte_seqence, GVAR(QTEHistory)]] call CBA_fnc_localEvent; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[_onDisplay, [_args, _qte_seqence, GVAR(QTEHistory)]] call CBA_fnc_localEvent; | |
[_onDisplay, [_args, _qte_sequence, GVAR(QTEHistory)]] call CBA_fnc_localEvent; |
addons/common/fnc_keyPressedQTE.sqf
Outdated
if (_onDisplay isEqualType "") then { | ||
[_onDisplay, [_args, _qte_seqence, GVAR(QTEHistory)]] call CBA_fnc_localEvent; | ||
} else { | ||
[_args, _qte_seqence, GVAR(QTEHistory)] call _onDisplay; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[_args, _qte_seqence, GVAR(QTEHistory)] call _onDisplay; | |
[_args, _qte_sequence, GVAR(QTEHistory)] call _onDisplay; |
addons/common/fnc_runQTE.sqf
Outdated
_onDisplay - Code callback on displayable event passed [_args, _qte_seqence, _qte_history]. <CODE, STRING> | ||
_onFinish - Code callback on QTE completed passed [_args, _elapsedTime]. <CODE, STRING> | ||
_onFinish - Code callback on QTE timeout/outranged passed [_args, _elapsedTime]. <CODE, STRING> | ||
_qte_seqence - QTE seqence usually made up of ["↑", "↓", "→", "←"] <ARRAY> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_qte_seqence - QTE seqence usually made up of ["↑", "↓", "→", "←"] <ARRAY> | |
_qte_seqence - QTE sequence usually made up of ["↑", "↓", "→", "←"] <ARRAY> |
addons/common/fnc_runQTE.sqf
Outdated
|
||
Example: | ||
[ | ||
car, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of tabs in this file at least.
[5] call CBA_fnc_generateQTESequence; | ||
|
||
Returns: | ||
QTE seqence of requested length made up of ["↑", "↓", "→", "←"] <ARRAY> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QTE seqence of requested length made up of ["↑", "↓", "→", "←"] <ARRAY> | |
QTE sequence of requested length made up of ["↑", "↓", "→", "←"] <ARRAY> |
addons/common/fnc_keyPressedQTE.sqf
Outdated
private _onFinish = GVAR(QTEArgs) get "onFinish"; | ||
private _onFail = GVAR(QTEArgs) get "onFail"; | ||
private _max_distance = GVAR(QTEArgs) get "max_distance"; | ||
private _qte_seqence = GVAR(QTEArgs) get "qte_seqence"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private _qte_seqence = GVAR(QTEArgs) get "qte_seqence"; | |
private _qte_sequence = GVAR(QTEArgs) get "qte_sequence"; |
addons/common/fnc_keyPressedQTE.sqf
Outdated
GVAR(QTEHistory) pushBack _eventQTE; | ||
|
||
|
||
if (GVAR(QTEHistory) isEqualTo _qte_seqence) exitWith { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (GVAR(QTEHistory) isEqualTo _qte_seqence) exitWith { | |
if (GVAR(QTEHistory) isEqualTo _qte_sequence) exitWith { |
addons/common/fnc_keyPressedQTE.sqf
Outdated
}; | ||
}; | ||
|
||
if !(GVAR(QTEHistory) isEqualTo (_qte_seqence select [0, count GVAR(QTEHistory)])) then { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if !(GVAR(QTEHistory) isEqualTo (_qte_seqence select [0, count GVAR(QTEHistory)])) then { | |
if !(GVAR(QTEHistory) isEqualTo (_qte_sequence select [0, count GVAR(QTEHistory)])) then { |
addons/common/fnc_runQTE.sqf
Outdated
Parameters: | ||
_object - <OBJECT> | ||
_args - Extra arguments passed to the _on... functions<ARRAY> | ||
_onDisplay - Code callback on displayable event passed [_args, _qte_seqence, _qte_history]. <CODE, STRING> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_onDisplay - Code callback on displayable event passed [_args, _qte_seqence, _qte_history]. <CODE, STRING> | |
_onDisplay - Code callback on displayable event passed [_args, _qte_sequence, _qte_history]. <CODE, STRING> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't reviewed the functionality yet, this is mostly formatting related.
addons/common/fnc_keyPressedQTE.sqf
Outdated
Process Quick-Time Key Press | ||
|
||
Parameters: | ||
_eventQTE - <STRING> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argument needs description.
addons/common/fnc_keyPressedQTE.sqf
Outdated
["↑"] call CBA_fnc_keyPressedQTE; | ||
|
||
Returns: | ||
Nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be None
, but the whole point of using a function over an event is so that you can return something.
We want to "override" input if it's a valid QTE keypress, meaning that e.g. if you have bound your arrow up key to move forwards, you wouldn't move forwards while you are doing a QTE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this where we return true/false in terms of input override?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep
addons/common/fnc_runQTE.sqf
Outdated
TRACE_1("QTE already running qeueing up",GVAR(QTERunning)); | ||
[{ | ||
!GVAR(QTERunning) | ||
}, { | ||
_this call FUNC(runQTE); | ||
}, _this] call CBA_fnc_waitUntilAndExecute; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not a fan of this. Depending, we might have to wait indefinitely. It also means that multiple QTE can queue up, which could cause unforeseen headaches, albeit unlikely.
I think we'd be better off returning a boolean telling the caller if the QTE was successfully run or not.
addons/common/fnc_runQTE.sqf
Outdated
["start_time", _start_time], | ||
["timeout", _timeout] | ||
]; | ||
GVAR(QTEArgs) = createHashMapObject [_qteArgsArray]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, there is no reason to use a hashmap object.
GVAR(QTEArgs) = createHashMapObject [_qteArgsArray]; | |
GVAR(QTEArgs) = createHashMapFromArray [_qteArgsArray]; |
addons/common/fnc_runQTE.sqf
Outdated
} else { | ||
[_args, _elapsedTime] call _onFail; | ||
}; | ||
}, _this] call CBA_fnc_waitUntilAndExecute; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't pass _this
when using default arguments. The default arguments are not inserted into _this
, you'll have to pass each argument individually in an array.
Regardless, _this
here does not make sense. Pass [_object, _start_time, _timeout, _max_distance]
and read those in the loop instead - unless reading from GVAR(QTEArgs)
is faster?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Most files use tabs instead of spaces.
-
The fnc headers are different from the ones in use. For ex: 698aee1
-
Apart from a couple extra tabs/spaces I added a suggestion for, lgtm.
addons/common/fnc_keyPressedQTE.sqf
Outdated
[_onDisplay, [_args, _qte_sequence, GVAR(QTEHistory)]] call CBA_fnc_localEvent; | ||
} else { | ||
[_args, _qte_sequence, GVAR(QTEHistory)] call _onDisplay; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[_onDisplay, [_args, _qte_sequence, GVAR(QTEHistory)]] call CBA_fnc_localEvent; | |
} else { | |
[_args, _qte_sequence, GVAR(QTEHistory)] call _onDisplay; | |
[_onDisplay, [_args, _qte_sequence, GVAR(QTEHistory)]] call CBA_fnc_localEvent; | |
} else { | |
[_args, _qte_sequence, GVAR(QTEHistory)] call _onDisplay; |
Co-authored-by: johnb432 <[email protected]>
Co-authored-by: johnb432 <[email protected]>
Co-authored-by: johnb432 <[email protected]>
Co-authored-by: johnb432 <[email protected]>
Co-authored-by: johnb432 <[email protected]>
Is there a linter in the repo I can run or format config just to save time on these formatting comments? |
Co-authored-by: johnb432 <[email protected]>
Co-authored-by: johnb432 <[email protected]>
Co-authored-by: johnb432 <[email protected]>
Thanks for the reviews guys sorry its 90% formatting issues. |
addons/common/XEH_preInit.sqf
Outdated
@@ -78,3 +79,19 @@ activateAddons GVAR(addons); | |||
["CAManBase", "InitPost", CBA_fnc_randomizeFacewear] call CBA_fnc_addClassEventHandler; | |||
|
|||
ADDON = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the code should be added before this line.
However, more importantly adding keybinds in common
doesn't work. keybinding
depends on common
, meaning the code below is called when CBA_fnc_addKeybind
is not defined.
This means that this code needs to be moved to another component. I'm not sure if events
is the right place or if we should add another component, just for this.
Co-authored-by: johnb432 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's looking pretty good, but some changes are needed.
addons/quicktime/XEH_preStart.sqf
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need this file, remove it.
class Extended_PreStart_EventHandlers { | ||
class ADDON { | ||
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); | ||
}; | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove along with the file.
addons/quicktime/CfgFunctions.hpp
Outdated
PATHTO_FNC(runQTE); | ||
PATHTO_FNC(keyPressedQTE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Order them alphabetically.
PATHTO_FNC(runQTE); | |
PATHTO_FNC(keyPressedQTE); | |
PATHTO_FNC(keyPressedQTE); | |
PATHTO_FNC(runQTE); |
addons/quicktime/fnc_runQTE.sqf
Outdated
if (GVAR(QTERunning)) exitWith { | ||
false | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GVAR(QTERunning)
is undefined on the first time it's run.
if (GVAR(QTERunning)) exitWith { | |
false | |
}; | |
if !(missionNamespace getVariable [QGVAR(QTERunning), false]) exitWith { | |
false | |
}; |
You could move this line above the params
line, as this doesn't require any arguments.
addons/quicktime/fnc_runQTE.sqf
Outdated
["onFinish", _onFinish], | ||
["onFail", _onFail], | ||
["maxDistance", _maxDistance], | ||
["qteSeqence", _qteSequence], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor typo has slipped in (change where necessary).
["qteSeqence", _qteSequence], | |
["qteSequence", _qteSequence], |
addons/quicktime/fnc_runQTE.sqf
Outdated
private _onFail = (GVAR(QTEArgs) get "onFail"); | ||
private _args = (GVAR(QTEArgs) get "args"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary parenthesis:
private _onFail = (GVAR(QTEArgs) get "onFail"); | |
private _args = (GVAR(QTEArgs) get "args"); | |
private _onFail = GVAR(QTEArgs) get "onFail"; | |
private _args = GVAR(QTEArgs) get "args"; |
|
||
GVAR(QTEHistory) pushBack _eventQTE; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Check if the input corresponds to the sequence |
}; | ||
true | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// If the user failed an input, wipe the previous input from memory |
addons/quicktime/fnc_runQTE.sqf
Outdated
private _maxDistance = GVAR(QTEArgs) get "maxDistance"; | ||
private _elapsedTime = CBA_missionTime - (GVAR(QTEArgs) get "startTime"); | ||
|
||
!GVAR(QTERunning) || player distance _object > _maxDistance || _elapsedTime > _timeout; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having player distance _object > _maxDistance
as a condition is a very limiting factor. In some cases one might not want or need to have such a condition, but would rather use others.
The condition code should be passed by the user, it would be {false}
by default (meaning the timeout would be the default method of ending the QTE if it isn't solved in time). object
and maxDistance
would no longer be needed.
You'd evaluate it by calling _args call _condition
, with _args
being the same args as the event/function one.
The function header would need to be adjusted accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not go a step further and remove the timeout and just pass [_args, _elapsedTime]
. This would allow for unlimited time variants too. Its also standard for all functions then.
addons/quicktime/fnc_runQTE.sqf
Outdated
---------------------------------------------------------------------------- */ | ||
|
||
|
||
params ["_object", "_args", "_onDisplay", "_onFinish", "_onFail", "_qteSequence", ["_maxDistance", 10], ["_timeout", 30]]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a public function, we need to sanitise the input:
params ["_object", "_args", "_onDisplay", "_onFinish", "_onFail", "_qteSequence", ["_maxDistance", 10], ["_timeout", 30]]; | |
params [["_object", objNull, [objNull]], "_args", ["_onDisplay", {}, ["", {}]], ["_onFinish", {}, ["", {}]], ["_onFail", {}, ["", {}]], ["_qteSequence", [], [[]]], ["_maxDistance", 10, [0]], ["_timeout", 30, [0]]]; |
You need to check if the input are valid (e.g. an empty QTE sequence should not be allowed).
I haven't taken into account the other proposals I've made, so you'll need to adapt accordingly.
Decided to go down the maximum flexibility route. We will let users define their conditions of failure entirely. I'm also passing a reset count so attempts can be implemented. |
Quick glance over changes: Looks good, but I'll take a more detailed look later. |
Is there any progress on this? |
Aside from the typo I saw, I played around with this. It's really nice, I like the configuration aspects to it too. I did a bunch of things with it and couldn't find a way to break it. Nice job. |
Co-authored-by: Mike-MF <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Is there anything that I need to do here now or is it just a case of wait? |
This system needs accessibility considerations.
|
Should I consider these must-haves before it can be merged? The original intent was for this to provide an activity for the player during ACE actions (bandaging, injecting, changing wheels etc) it was always intended that there would be a setting in ACE to set if completing the action would be required or just speed the action up a bit. There are use-cases where a simple timeout may not be appropriate eg any activity where the code must be completed within a set time otherwise failure. Its also possible to use something like Voice Attack so you can simply say the key code and it will input it in for you. |
imo number 1 is a must have. |
@Drofseh You, can now turn on an option to make all QTEs only one button. |
When merged this pull request will:
Provide Quick Time Events for players to enter in order to complete action (capability addition not change any existing functionality)
Respect the Submitting Content Guidelines
Migrated from Add Quick Time Events acemod/ACE3#9849